home *** CD-ROM | disk | FTP | other *** search
/ Super PC 34 / Super PC 34 (Shareware).iso / spc / UTIL / DJGPP2 / V2MISC / CSDPMI1S.ZIP / SRC / CWSDPMI / CONTROL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-04  |  12.3 KB  |  407 lines

  1. /* Copyright (C) 1995 CW Sandmann (sandmann@clio.rice.edu) 102 Hurst Ct, Destrehan, LA 70047
  2. ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  3. **
  4. ** This file is distributed under the terms listed in the document
  5. ** "copying.cws", available from CW Sandmann at the address above.
  6. ** A copy of "copying.cws" should accompany this file; if not, a copy
  7. ** should be available from where this file was obtained.  This file
  8. ** may not be distributed without a verbatim copy of "copying.cws".
  9. **
  10. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  11. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. */
  13. /* PC98 support contributed 6-95 tantan SGL00213@niftyserve.or.jp */
  14.  
  15. #include <dos.h>
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <fcntl.h>
  19. #include <string.h>
  20. #include <io.h>
  21.  
  22. #include "gotypes.h"
  23. #include "gdt.h"
  24. #include "idt.h"
  25. #include "tss.h"
  26. #include "valloc.h"
  27. #include "utils.h"
  28. #include "vcpi.h"
  29. #include "paging.h"
  30. #include "exphdlr.h"
  31. #include "dalloc.h"
  32. #include "mswitch.h"
  33. #include "xms.h"
  34. #include "control.h"
  35. #include "dpmisim.h"
  36.  
  37. /* Note, the near heap and stack are pooled, a big env just means less tasks */
  38. /* We must add 0x100 paragraphs required to the exe header for the 4K below */
  39. extern unsigned _heaplen = 1024U;    /* observed is around 500 + env size */
  40. extern unsigned _stklen = 3072U;    /* 0x38+dpmisim per nested task, 9 tasks */
  41. extern unsigned int _brklvl[2];        /* hi word is free seg after our prog */
  42. extern void _restorezero(void);
  43.  
  44. int show_memory_info = 1;
  45. static word16 current_es = 0;
  46. static word16 old_env,current_psp;
  47. static word8 one_pass = 1;
  48. word8 mtype = 0;            /* Machine type */
  49.  
  50. DESC_S gdt[g_num];
  51. DESC_S ldt[l_num];
  52. IDT idt[256];
  53. TSS *tss_ptr;
  54.  
  55. word8 vcpi_installed = 0;    /*  VCPI Installed Flag  */
  56. word8 use_xms=0;
  57.  
  58. CWSDPMI_pblk CWSpar = { "CWSPBLK", "c:\\cwsdpmi.swp", 0, 0, 64, 3840 };
  59.  
  60. static char *exception_names[] = {
  61.   "Division by Zero",
  62.   "Debug",
  63.   "NMI",
  64.   "Breakpoint",
  65.   "Overflow",
  66.   "Bounds Check",
  67.   "Invalid Opcode",
  68.   "Coprocessor not available",
  69.   "Double Fault",
  70.   "Coprocessor overrun",
  71.   "Invalid TSS",
  72.   "Segment Not Present",
  73.   "Stack Fault",
  74.   "General Protection Fault",
  75.   "Page fault",
  76.   0,
  77.   "Coprocessor Error",
  78. };
  79. #define EXCEPTION_COUNT (sizeof(exception_names)/sizeof(exception_names[0]))
  80.  
  81. word16 get_pid(void)
  82. {
  83.   _AH = 0x62;
  84.   geninterrupt(0x21);
  85.   return _BX;
  86. }
  87.  
  88. void set_pid(word16 pid)
  89. {
  90.   _BX = pid;
  91.   _AH = 0x50;
  92.   geninterrupt(0x21);
  93. }
  94.  
  95. static void fill_desc(DESC_S *g, word32 limit, word32 base, word8 type, int G)
  96. {
  97.   if (G & 2)            /* Granularity bit = 4K */
  98.     limit = limit >> 12;
  99.   g->lim0 = (word16)limit;
  100.   g->lim1 = (limit>>16) & 0x0f;
  101.   g->base0 = (word16)base;
  102.   g->base1 = (word8)(base>>16);
  103.   g->base2 = (word8)(base>>24);
  104.   g->stype = type;
  105.   g->lim1 |= G * 0x40;        /* Shift field to set G & D bits */
  106. }
  107.  
  108. static void setup_tss(TSS *t, void (*eip)())
  109. {
  110.   memset(t, 0, sizeof(TSS));
  111.   /* At this point EFLAGS = 0 (interrupt disabled) and all selectors null */
  112.   t->tss_cs = g_rcode*8;
  113.   (word16)t->tss_eip = FP_OFF(eip);
  114.   t->tss_ss0 = t->tss_ss = t->tss_ds = g_rdata*8;
  115.   (word16)t->tss_esp0 = (word16)t->tss_esp = FP_OFF(t->tss_stack);
  116.   t->tss_ldt = g_ldt*8;
  117. }
  118.  
  119. /* This routine is called in context of the other process */
  120. void cleanup(int exitcode)
  121. {
  122.   int lastused;
  123.   word16 far *envptr;
  124.   envptr = MK_FP(current_psp,0x2c);
  125.   *envptr = old_env;
  126.  
  127.   lastused = a_tss.tss_lastused;
  128.   current_es = a_tss.tss_cur_es;        /* Saved ES if needed */
  129.   old_env = a_tss.tss_old_env;
  130.   current_psp = a_tss.tss_cur_psp;
  131.   if (current_es) {            /* There is back link, restore old TSS */
  132.     AREAS *area = firstarea;
  133.     AREAS **lasta = &firstarea;
  134.     word16 lua = (word16)lastused >> 8;
  135.     while (lua--) {
  136.       lasta = &area->next;
  137.       area = area->next;
  138.     }
  139.     while (*lasta && free_memory_area((*lasta)->first_addr)) ;
  140.     lastused &= 0xff;
  141.     for(lastused++; lastused<l_num; lastused++)
  142.       ldt[lastused].stype = 0;        /* Mark them all as available */
  143.  
  144.     movedata(current_es, 0, _DS, FP_OFF(&a_tss), 6*16);
  145.   } else {                /* This is the last nested process */
  146.     dalloc_uninit();
  147.     uninit_controllers();
  148.     valloc_uninit();
  149.     if (one_pass || a_tss.tss_ebx == ONE_PASS_MAGIC) { /* "magic" for unload */
  150.       setvect(0x2f,oldint2f);
  151.  
  152.       ems_free();        /* Deallocated EMS Page */
  153.  
  154.       disable();
  155.       _ES = _psp;        /* Deallocate TSR we are currently executing! */
  156.       _AH = 0x49;
  157.       geninterrupt(0x21);
  158.     }
  159.   }
  160.  
  161.   reset_a20();
  162.   _AL = (word8)exitcode;
  163.   _AH = 0x4c;
  164.   geninterrupt(0x21);
  165. }
  166.  
  167. void do_faulting_finish_message(void)
  168. {
  169.   extern char in_rmcb;
  170.   char *en = (tss_ptr->tss_irqn >= EXCEPTION_COUNT) ? 0 : exception_names[tss_ptr->tss_irqn];
  171.   if (en == 0)
  172.     fprintf(stderr, "Interrupt 0x%02x", tss_ptr->tss_irqn);
  173.   else
  174.     fprintf(stderr, "%s", en);
  175.   if(tss_ptr->tss_irqn == 14)
  176.     fprintf(stderr, " cr2=%08lx", tss_ptr->tss_cr2);
  177.   if(in_rmcb)
  178.     fprintf(stderr, " in RMCB");
  179.   fprintf(stderr, " at eip=%lx; flags=%x\n", tss_ptr->tss_eip, (word16)tss_ptr->tss_eflags);
  180.   fprintf(stderr, "eax=%08lx ebx=%08lx ecx=%08lx edx=%08lx esi=%08lx edi=%08lx\n",
  181.     tss_ptr->tss_eax, tss_ptr->tss_ebx, tss_ptr->tss_ecx, tss_ptr->tss_edx,
  182.     tss_ptr->tss_esi, tss_ptr->tss_edi);
  183.   fprintf(stderr, "ebp=%08lx esp=%08lx cs=%x ds=%x es=%x fs=%x gs=%x ss=%x error=%04x\n",
  184.     tss_ptr->tss_ebp, tss_ptr->tss_esp,
  185.     tss_ptr->tss_cs, tss_ptr->tss_ds, tss_ptr->tss_es, tss_ptr->tss_fs,
  186.     tss_ptr->tss_gs, tss_ptr->tss_ss, (word16)tss_ptr->tss_error);
  187.   cleanup(1);
  188. }
  189.  
  190. void main1(void)    /* int argc, char **argv) */
  191. {
  192.   /* Check for cpu type in assembly main to avoid 8088 problems with 'enter' */
  193.   
  194.   if (_osmajor < 3) {
  195.     fprintf(stderr, "DOS 3 required.\n");
  196.     exit(1);
  197.   }
  198.  
  199.   if(*(word16 far *)MK_FP(0xf000, 0xfff3) == 0xfd80) {
  200.     hard_slave_lo = 0x10;        /* PC98 slave */
  201.     mtype = PC98;
  202.   }
  203.  
  204.   _restorezero();
  205.  
  206. #if run_ring != 0
  207.   dalloc_file(CWSpar.swapname);        /* default */
  208. #endif
  209.   {
  210.   char far *ptr;
  211.   int i,nc;
  212.   
  213.   ptr = MK_FP(_psp, 0x80);
  214.   nc = *ptr++;
  215.   ptr[nc] = 0;
  216.   for(i=0;i<nc;i++) {
  217.     if(ptr[i] == '-') {
  218.       char test = 0x20 | ptr[++i];    /* make lower case if upper */
  219.       fprintf(stderr,"CWSDPMI V0.90+ (r1) Copyright (C) 1995 CW Sandmann  ABSOLUTELY NO WARRANTY\n");
  220.       if(test == 'p')            /* persistent, permanent */
  221.         one_pass = 0;
  222.       else if(test == 'u') {        /* unload */
  223.         extern void unload_tsr(void);
  224.         unload_tsr();
  225.       } else if(test == 's'){        /* swapfile; -s- means no virtual mem */
  226.         int j;
  227.         char t;
  228.         char *swap = malloc(nc-i);
  229.         for(j=0,i++,t=32;t;i++){
  230.           t = ptr[i];
  231.           if(t != ' ' && t != 9)    /* skip whitespace */
  232.             swap[j++] = t;
  233.         }
  234. #if run_ring != 0
  235.         if(swap[0] == '-')
  236.           swap[0] = 0;
  237.         dalloc_file(swap);
  238. #endif
  239.       }
  240.     }
  241.   }
  242.   }
  243.   _ES = peek(_psp,0x2c);    /* Deallocate TSR environment */
  244.   _AH = 0x49;
  245.   geninterrupt(0x21);
  246.   _close(0); _close(1);        /* Close stdin, stdout, AUX, PRN */
  247.   _close(3); _close(4);
  248.  
  249.   use_xms = xms_installed();
  250.  
  251.   ems_init();
  252.   if (cpumode()) {        /* We are in V86 mode */
  253.     if (!(vcpi_installed = vcpi_present())) {
  254.       ems_free();
  255.       fprintf(stderr, "Protected mode not accessible.\n");
  256.       exit(1);
  257.     }
  258.   }
  259.  
  260.   _BX = 2; _AH = 0x3e; geninterrupt(0x21);    /* Close stderr, tc thinks open */
  261. #if run_ring != 0
  262.   gdt[g_iret].lim0 = (word16)ring0_iret;    /* Call gate to do IRET */
  263.   gdt[g_iret].base0 = g_rcode*8;
  264.   gdt[g_iret].stype = SEL_PRV | 0x8c;
  265. #else
  266.   fill_desc(&gdt[g_iret], sizeof(TSS)-1, ptr2linear(&f_tss), 0x89, 1);
  267. #endif
  268.   fill_desc(&gdt[g_gdt], sizeof(gdt)-1, ptr2linear(gdt), 0x92, 0);
  269.   fill_desc(&gdt[g_idt], sizeof(idt)-1, ptr2linear(idt), 0x92, 0);
  270.   fill_desc(&gdt[g_ldt], sizeof(ldt)-1, ptr2linear(ldt), 0x82, 1);
  271.   fill_desc(&gdt[g_rcode], 0xffff, (word32)_CS*16L, 0x9a, 0);
  272.   fill_desc(&gdt[g_rdata], 0xffff, (word32)_DS*16L, 0x92, 1); /* 1 for ring 3 */
  273.   fill_desc(&gdt[g_core], 0xffffffffL, 0, SEL_PRV | 0x92, 3);
  274.   fill_desc(&gdt[g_BIOSdata], 0xffff, (word32)0x400, SEL_PRV | 0x92, 0);
  275.   fill_desc(&gdt[g_pcode], 0xffff, (word32)_CS*16L, SEL_PRV | 0x9a, 0);
  276.   fill_desc(&gdt[g_pdata], 0xffff, (word32)_DS*16L, SEL_PRV | 0x92, 1);
  277.  
  278.   fill_desc(&gdt[g_ctss], sizeof(TSS)-1, ptr2linear(&c_tss), SEL_PRV | 0x89, 1);
  279.   fill_desc(&gdt[g_atss], sizeof(TSS)-1, ptr2linear(&a_tss), 0x89, 1);
  280.   fill_desc(&gdt[g_itss], sizeof(TSS)-1, ptr2linear(&i_tss), SEL_PRV | 0x89, 1);
  281.  
  282.   oldint2f = getvect(0x2f);
  283.   setvect(0x2f, dpmiint2f);
  284.  
  285.   DPMIsp = _SP;
  286.   _DX = _brklvl[1] - _psp;
  287.   _AX = 0x3100;
  288.   geninterrupt(0x21);
  289. }
  290.  
  291. void DPMIstartup(void)
  292. {
  293.   {
  294.   int use32,myES;
  295.   int acode,adata,apsp,aenv,astack;
  296.   int lastused;        /* Keep track of selectors */
  297.   word16 dpmipsp;
  298.   word16 far *envptr;
  299.   myES = _ES;
  300.   tss_ptr = &a_tss;
  301.   if (current_es){
  302.     int lua = 0;        /* Last used area */
  303.     AREAS *area = firstarea;
  304.     while (area) {
  305.      lua++;
  306.      area = area->next;
  307.     }
  308.     for(lastused=l_num-1;lastused>l_free && !(ldt[lastused].stype); lastused--);
  309.     lastused |= lua << 8;
  310.     movedata(_DS, FP_OFF(&a_tss), current_es, 0, 6*16); /* Save old TSS */
  311.     acode = alloc_ldt(1);
  312.     adata = alloc_ldt(1);
  313.     apsp = alloc_ldt(1);
  314.     aenv = alloc_ldt(1);
  315.   } else {
  316.     int i,n;
  317.     setup_tss(&c_tss, go_real_mode);
  318.     setup_tss(&a_tss, go_real_mode);
  319.     setup_tss(&o_tss, go_real_mode);
  320. #if run_ring == 0
  321.     { void double_fault(void); setup_tss(&f_tss, double_fault); }
  322. #else
  323.     setup_tss(&f_tss, go_real_mode);
  324. #endif
  325.     setup_tss(&i_tss, interrupt_common);
  326.  
  327.     memset(ldt,0,sizeof(ldt));    /* Zero it; this make all stypes = 0 not used */
  328.     lastused=l_free-1;        /* lua = 0 */
  329.     /* Note - this shortcut will make these look free to alloc_ldt until set */
  330.     acode = l_acode;
  331.     adata = l_adata;
  332.     apsp = l_apsp;
  333.     aenv = l_aenv;
  334.     dr[7] = 0L;            /* Clear all breakpoints */
  335.  
  336.     valloc_init();
  337.     dalloc_init();
  338.     paging_setup();
  339.     init_controllers();
  340.  
  341.     n = (int)ivec1-(int)ivec0;
  342.     for (i=0; i<256; i++)
  343.     {
  344.       idt[i].selector = GDT_SEL(g_pcode);
  345.       idt[i].stype = 0xee00;
  346.       idt[i].offset0 = (int)FP_OFF(ivec0) + n*i;
  347.       idt[i].offset1 = 0;
  348.     }
  349.     for (i=0; i<16; i++)
  350.       idt[i].selector = g_rcode*8;
  351.     for (i=hard_master_lo; i<=hard_master_hi; i++)
  352.       idt[i].selector = g_rcode*8;
  353.     for (i=hard_slave_lo; i<=hard_slave_hi; i++)
  354.       idt[i].selector = g_rcode*8;
  355. #ifdef I31PROT
  356.     idt[0x31].offset0 = (int)FP_OFF(ivec31);
  357. #endif
  358.     idt[7].offset0 = (int)ivec7;        /* To handle TS bit set faults */
  359. #if run_ring == 0
  360.     i = 8;    /* Double fault */
  361.     idt[i].selector = g_iret*8; idt[i].stype = 0xe500; idt[i].offset0 = 0;
  362. #endif
  363.   }
  364.   movedata(myES, 32, _DS, FP_OFF(&a_tss.tss_eip), 4*14);
  365.  
  366.   use32 = (word16)a_tss.tss_eax & 1;
  367.  
  368.   /* Hack alert! Since ring1 & ring2 not used, I re-used this storage to keep
  369.      track of selector usage (to aid clean up), back link to the previous 
  370.      allocated area segment, the old environment segment, and the PSP */
  371.  
  372.   a_tss.tss_cur_es = current_es;    /* Back link to saved TSS */
  373.   a_tss.tss_lastused = lastused;
  374.   current_es = myES;            /* Save mine for child if any */
  375.   a_tss.tss_old_env = old_env;        /* Saved */
  376.   a_tss.tss_cur_psp = current_psp;
  377.  
  378.   a_tss.tss_fs = a_tss.tss_gs = 0;
  379.   fill_desc(&ldt[acode], 0xffff, (word32)a_tss.tss_cs*16L, SEL_PRV | 0x9a, 0);
  380.   a_tss.tss_cs = LDT_SEL(acode);
  381.   fill_desc(&ldt[adata], 0xffff, (word32)a_tss.tss_ds*16L, SEL_PRV | 0x92, use32);
  382.   a_tss.tss_eflags = 0x3202;
  383.  
  384.   _AH = 0x62;                /* Get PSP */
  385.   geninterrupt(0x21);
  386.   dpmipsp = _BX;
  387.   current_psp = dpmipsp;
  388.   envptr = MK_FP(dpmipsp,0x2c);
  389.   old_env = *envptr;
  390.   *envptr = LDT_SEL(aenv);
  391.   fill_desc(&ldt[apsp], 0xffff, (word32)dpmipsp*16L, SEL_PRV | 0x92, 0); /* lim should be ff */
  392.   a_tss.tss_es = LDT_SEL(apsp);
  393.   fill_desc(&ldt[aenv], 0xffff, (word32)old_env*16L, SEL_PRV | 0x92, 0);
  394.   /* Must come after all other descriptors set up, since calls alloc_ldt() */
  395.   if (a_tss.tss_ds != a_tss.tss_ss) {
  396.     astack = alloc_ldt(1);
  397.     fill_desc(&ldt[astack], 0xffff, (word32)a_tss.tss_ss*16L, SEL_PRV | 0x92, use32);
  398.   } else
  399.     astack = adata;
  400.  
  401.   a_tss.tss_ds = LDT_SEL(adata);
  402.   a_tss.tss_ss = LDT_SEL(astack);
  403.   setvect(0x23,int23);
  404.   setvect(0x24,int24);
  405.   }
  406. }
  407.